package com.mofum.scope.annotation.service.parser;

import com.mofum.scope.annotation.service.ColumnScope;
import com.mofum.scope.annotation.service.TableScope;
import com.mofum.scope.common.annotation.AnnotationParser;
import com.mofum.scope.common.annotation.metadata.service.MColumnScope;
import com.mofum.scope.common.annotation.metadata.service.MTableScope;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author yuyang@qxy37.com
 * @since 2019-03-20
 **/
public class TableScopeParser<T> implements AnnotationParser<Class<T>, MTableScope> {

    public Map<Field, MTableScope> parseField(Class<T> tClass) {

        Map<Field, MTableScope> map = new HashMap<Field, MTableScope>();

        Field[] fields = tClass.getDeclaredFields();

        for (Field field : fields) {

            if (field.isAnnotationPresent(TableScope.class)) {

                TableScope atColumn = field.getAnnotation(TableScope.class);

                map.put(field, parse(atColumn));

            }

        }

        return map;
    }

    public Map<Type, MTableScope> parseType(Class<T> tClass) {

        Map<Type, MTableScope> map = new HashMap<Type, MTableScope>();

        Class<?> clazz = tClass;

        if (clazz.isAnnotationPresent(TableScope.class)) {

            TableScope atColumn = clazz.getAnnotation(TableScope.class);

            map.put(clazz, parse(atColumn));

        }

        return map;
    }

    public Map<Method, MTableScope> parseMethod(Class<T> tClass) {

        Map<Method, MTableScope> map = new HashMap<Method, MTableScope>();

        Method[] methods = tClass.getDeclaredMethods();

        for (Method method : methods) {

            if (method.isAnnotationPresent(TableScope.class)) {

                TableScope atColumn = method.getAnnotation(TableScope.class);

                map.put(method, parse(atColumn));

            }

        }

        return map;
    }

    public Map<Method, List<MTableScope>> parseParams(Class<T> tClass) {

        Map<Method, List<MTableScope>> map = new HashMap<Method, List<MTableScope>>();

        Method[] methods = tClass.getDeclaredMethods();

        for (Method method : methods) {

            List<MTableScope> list = new ArrayList<MTableScope>();

            Annotation[][] parameterAnnotations = method.getParameterAnnotations();

            for (Annotation[] parameterAnnotation : parameterAnnotations) {
                for (Annotation annotation : parameterAnnotation) {
                    if (annotation instanceof TableScope) {
                        TableScope atColumn = (TableScope) annotation;
                        list.add(parse(atColumn));
                    }
                }
            }

            map.put(method, list);
        }

        return map;
    }

    public MTableScope parse(TableScope tableScope) {
        MTableScope mTableScope = new MTableScope();
        mTableScope.setName(tableScope.value());
        mTableScope.setAlias(tableScope.alias());
        ColumnScope[] columnScopes = tableScope.columns();

        if (columnScopes != null) {

            MColumnScope[] mColumnScopes = new MColumnScope[columnScopes.length];

            ColumnScopeParser columnScopeParser = new ColumnScopeParser();

            for (int i = 0; i < columnScopes.length; i++) {

                mColumnScopes[i] = columnScopeParser.parse(columnScopes[i]);

            }

            mTableScope.setColumns(mColumnScopes);
        }


        return mTableScope;
    }

}


